"""

"""
import numpy as np
import time
import sys
import os

import seq2seq_prediction

if sys.version_info.major == 2:
    import Tkinter as tk
else:
    import tkinter as tk
import lstm_prediction

baselines = {
    'glimpse_mobility': 0,
    # 'without_mobility': 1,
    'linear_mobility': 1,
    'seq2seq_mobility': 2,
    'perfect_mobility': 3,
}
# baselines = 'glimpse_mobility'

UNIT = 40  # pixels
MAZE_H = 4  # grid height
MAZE_W = 4  # grid width

Bwc = 2e6  # 2Mhz
A = 4.11  # 天线增益
f = 9.15e8  # 915Mhz
P = 0.25  # W 用户设备天线的发射功率
sigma = 1e-10
PI = 3.1415926
Din = 2.7e5  # 270KB
Ptask = 1.08e6  # 1080KB
Ci = 6.3e7  # 63MB/s
Kuser = np.zeros(50000)
Kuser_episode = np.zeros(3000)
Kaverage = 0
Kaverage_danci = 0
Trans_average = 0
Tcomp_average = 0
Tmig_average = 0
Timeall_average = 0
Vm_size = 1e9 / 8
B = 1e9 / 8  # 1Gbps=1/8 GB
Dmig = B
Last_action = 0
C = np.zeros(35)
tau = 5  # τ
tau_ = 15  # τ'
Time_ = 0
unit = 10
# 动作指令集
action_dict = {0: [0, 0], 1: [100, 0], 2: [200, 0], 3: [300, 0], 4: [400, 0], 5: [500, 0], 6: [600, 0.0],
               7: [0, 100], 8: [100, 100], 9: [200, 100], 10: [300, 100], 11: [400, 100], 12: [500, 100],
               13: [600, 100],
               14: [0, 200], 15: [100, 200], 16: [200, 200], 17: [300, 200], 18: [400, 200], 19: [500, 200],
               20: [600, 200],
               21: [0, 300], 22: [100, 300], 23: [200, 300], 24: [300, 300], 25: [400, 300], 26: [500, 300],
               27: [600, 300],
               28: [0, 400], 29: [100, 400], 30: [200, 400], 31: [300, 400], 32: [400, 400], 33: [500, 400],
               34: [600, 400],
               }


def loadDatadet(infile, k):
    f = open(infile, 'r')
    sourceInLine = f.readlines()
    dataset = []
    for line in sourceInLine:
        temp1 = line.strip('\n')
        temp2 = temp1.split('\t')  # 以tab为分割 我们应该是以空格分割？
        dataset.append(temp2)
    for i in range(0, len(dataset)):
        for j in range(k):
            dataset[i].append(float(dataset[i][j]))
        del (dataset[i][0:k])
    return dataset


file_num = 1
intercept_time = lstm_prediction.train_days + lstm_prediction.testing_days
Count_file = 0
path = "C:/Users/admin/Desktop/d2d_oneuser/NewYork_one"  # 文件夹目录
files = os.listdir(path)  # 得到文件夹下的所有文件名称
txts = []
for file in files:  # 遍历文件夹
    position = path + '\\' + file  # 构造绝对路径，"\\"，其中一个'\'为转义符
    data = loadDatadet(position, 3)
    txts.append(data)

maxnumx = 0
minnumx = 100000
maxnumy = 0
minnumy = 100000

for Count_file in range(file_num):  # 找到最大最小值
    for i in range(lstm_prediction.train_days, intercept_time):
        normalizex = float(txts[Count_file][i][2])
        if maxnumx < normalizex:
            maxnumx = normalizex
        if minnumx > normalizex:
            minnumx = normalizex
        normalizey = float(txts[Count_file][i][3])
        if maxnumy < normalizey:
            maxnumy = normalizey
        if minnumy > normalizey:
            minnumy = normalizey
userx = np.zeros((file_num, lstm_prediction.testing_days))
usery = np.zeros((file_num, lstm_prediction.testing_days))

L_u_old = np.zeros((2, 5))
m = np.zeros((2, 15))  # m未来的位置

Time = np.zeros((file_num, lstm_prediction.testing_days))
for Count_file in range(np.array(txts).shape[0]):
    # for i in range((np.array(txts[Count_file])).shape[0]):
    for i in range(lstm_prediction.train_days, intercept_time):
        userx[Count_file][i - lstm_prediction.train_days] = (txts[Count_file][i][2] - minnumx) * 600 / (
                maxnumx - minnumx)
        usery[Count_file][i - lstm_prediction.train_days] = (txts[Count_file][i][3] - minnumy) * 400 / (
                maxnumy - minnumy)
        Time[Count_file][i - lstm_prediction.train_days] = txts[Count_file][i][1]
Count_file = 0


class Mobility(tk.Tk, object):
    def __init__(self):
        super(Mobility, self).__init__()
        self.User_x = 0.0
        self.User_y = 0.0
        # self.e = np.zeros([5,7])
        self.e = np.zeros([2, 35])  # 每个服务器ei
        self.h = np.zeros(35)
        self.d = np.zeros(35)  # d是n维向量，每个元素是用户u与每个服务器ei之间的距离。
        self.b = 1.  # b也是一个n维向量，其中包括服务器根据准入控制约束可以服务的人数。
        self.L_u = np.zeros([2, tau])
        self.m = np.zeros([2, tau])
        self.m_ = np.zeros(10)
        self.t = 0
        self.t_use = 0
        self.state = None
        self.m_state = None
        self.counter = 0
        self.done = 0
        self.add = None
        self.reward = 0
        self.action_space = np.zeros(35)
        self.n_actions = len(action_dict)
        self.n_features = 48
        self.countmig = 0

    def step(self, action, episode):
        global Count_file
        # action = episode
        # self.User_x = float(userx[Count_file][self.t])
        # self.User_y = float(usery[Count_file][self.t])
        if baselines =='perfect_mobility':
            self.User_x = round(userx[Count_file][self.t]/ unit) * unit
            self.User_y = round(usery[Count_file][self.t]/ unit) * unit
        else:
            self.User_x = round(userx[Count_file][self.t] / unit) * unit
            self.User_y = round(usery[Count_file][self.t] / unit) * unit
        # print("User_x = ", self.User_x)
        # print("User_y = ", self.User_y)
        for i in range(lstm_prediction.n_timestamp):
            if lstm_prediction.n_timestamp <= self.t < (lstm_prediction.testing_days - lstm_prediction.n_timestamp):
                self.L_u[0][i] = userx[Count_file][self.t - i]
                self.L_u[1][i] = usery[Count_file][self.t - i]
        if baselines == 'glimpse_mobility':
            for n in range(lstm_prediction.n_timestamp):
                # if lstm_prediction.n_timestamp <= self.t < (lstm_prediction.testing_days - lstm_prediction.n_timestamp):
                #     self.m_[n] = (lstm_prediction.y_predicted_descaled_x[self.t - lstm_prediction.n_timestamp + n] - minnumx) * 600 / (maxnumx - minnumx)
                #     self.m_[n + lstm_prediction.n_timestamp] = (lstm_prediction.y_predicted_descaled_y[self.t - lstm_prediction.n_timestamp + n] - minnumy) * 400 / (maxnumy - minnumy)
                # else:
                #     self.m_[n] = userx[Count_file][self.t + 1 + n]
                #     self.m_[n + lstm_prediction.n_timestamp] = usery[Count_file][self.t + 1 + n]
                if lstm_prediction.n_timestamp <= self.t < (lstm_prediction.testing_days - lstm_prediction.n_timestamp):
                    self.m_[0] = (lstm_prediction.y_predicted_descaled_x[self.t - lstm_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[1] = (lstm_prediction.y_predicted_descaled_x_2[
                                      self.t - lstm_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[2] = (lstm_prediction.y_predicted_descaled_x_3[
                                      self.t - lstm_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[3] = (lstm_prediction.y_predicted_descaled_x_4[
                                      self.t - lstm_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[4] = (lstm_prediction.y_predicted_descaled_x_5[
                                      self.t - lstm_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[5] = (lstm_prediction.y_predicted_descaled_y[self.t - lstm_prediction.n_timestamp] - minnumy) * 400 / (maxnumy - minnumy)
                    self.m_[6] = (lstm_prediction.y_predicted_descaled_y_2[
                                          self.t - lstm_prediction.n_timestamp] - minnumy) * 400 / (maxnumy - minnumy)
                    self.m_[7] = (lstm_prediction.y_predicted_descaled_y_3[
                                          self.t - lstm_prediction.n_timestamp] - minnumy) * 400 / (maxnumy - minnumy)
                    self.m_[8] = (lstm_prediction.y_predicted_descaled_y_4[
                                           self.t - lstm_prediction.n_timestamp] - minnumy) * 400 / (maxnumy - minnumy)
                    self.m_[9] = (lstm_prediction.y_predicted_descaled_y_5[
                                          self.t - lstm_prediction.n_timestamp] - minnumy) * 400 / (maxnumy - minnumy)
                else:
                    self.m_[n] = userx[Count_file][self.t + 1 + n]
                    self.m_[n + lstm_prediction.n_timestamp] = usery[Count_file][self.t + 1 + n]
            # print("self.t =", self.t)
            # print("self.m_=", self.m_)
        elif baselines == 'linear_mobility':
            for n in range(lstm_prediction.n_timestamp):
                if lstm_prediction.n_timestamp <= self.t < (lstm_prediction.testing_days - lstm_prediction.n_timestamp):
                    self.m_[n] = (lstm_prediction.pre_linear_x[self.t - lstm_prediction.n_timestamp + n] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[n + lstm_prediction.n_timestamp] = (lstm_prediction.pre_linear_y[self.t - lstm_prediction.n_timestamp + n]-minnumy) * 400 / (maxnumy - minnumy)
                else:
                    self.m_[n] = userx[Count_file][self.t + 1 + n]
                    self.m_[n + lstm_prediction.n_timestamp] = usery[Count_file][self.t + 1 + n]
            # print("self.t =", self.t)
            # print("self.m_=", self.m_)
        elif baselines == 'seq2seq_mobility':
            for n in range(seq2seq_prediction.n_timestamp):
                if seq2seq_prediction.n_timestamp <= self.t < (seq2seq_prediction.testing_days - seq2seq_prediction.n_timestamp):
                    self.m_[n] = (seq2seq_prediction.y_predicted_descaled_x[n][self.t - seq2seq_prediction.n_timestamp] - minnumx) * 600 / (maxnumx - minnumx)
                    self.m_[n + seq2seq_prediction.n_timestamp] = (seq2seq_prediction.y_predicted_descaled_y[n][self.t - seq2seq_prediction.n_timestamp]-minnumy) * 400 / (maxnumy - minnumy)
                else:
                    self.m_[n] = userx[Count_file][self.t + 1 + n]
                    self.m_[n + lstm_prediction.n_timestamp] = usery[Count_file][self.t + 1 + n]
        elif baselines =='perfect_mobility':
            for n in range(seq2seq_prediction.n_timestamp):
                self.m_[n] = userx[Count_file][self.t + 1 + n]
                self.m_[n + seq2seq_prediction.n_timestamp] = usery[Count_file][self.t + 1 + n]
            # print("self.t =",self.t)
            # print("self.m_=",self.m_)

        for i in range(35):
            self.e[0][i] = 100 * (i % 7)
            self.e[1][i] = 100 * (i % 5)
            self.d[i] = round(np.sqrt((self.User_x - self.e[0][i]) ** 2 + (self.User_y - self.e[1][i]) ** 2))
            self.h[i] = A * ((3e8 / (4 * PI * f * self.d[i])) ** 2)  # 衰落信道
        self.b = 1.
        self.state = [self.User_x, self.User_y, self.b, self.d]
        # self.m_state = [self.User_x, self.User_y, self.b, self.d, self.m_]
        C[action] = Bwc * np.log2(1 + P * self.h[action] / (sigma ** 2))  # 香农容量
        Trans = Din / C[action]
        Tcomp = Ptask / Ci
        # Tmig = 0
        global Last_action, Time_, Trans_average, Tcomp_average, Tmig_average
        if Last_action == action:
            Tmig = 0
        else:
            Tmig = Dmig / (B / 2)
            self.countmig = self.countmig + 1
        # print("self.t = ", self.t)
        # print("action = ", action)
        # print("Tmig = ", Tmig)
        # Timeall_average = Trans_average + Tcomp_average + Tmig_average
        Kuser[self.t] = int((30 - Tmig) / (Trans + Tcomp))
        global Kaverage, Kaverage_danci
        if self.t > 0:
            # if episode == 0:
            Kaverage = (Kaverage * (self.t_use + self.t - 1) + Kuser[self.t - 1]) / (self.t_use + self.t)
            Trans_average = (Trans_average * (self.t_use + self.t - 1) + Trans) / (self.t_use + self.t)
            Tcomp_average = (Tcomp_average * (self.t_use + self.t - 1) + Tcomp) / (self.t_use + self.t)
            Tmig_average = (Tmig_average * (self.t_use + self.t - 1) + Tmig) / (self.t_use + self.t)
            # if (Kuser[self.t]) >= Kaverage:  # 二进制奖励函数
            #     self.reward = 1.0
            # else:
            #     self.reward = -1.0

            self.reward = (Kuser[self.t] - 1490) * 0.1  # 自定义奖励函数

        grid_Lu_x = round(self.User_x / unit) * unit
        grid_Lu_y = round(self.User_y / unit) * unit
        grid_d = np.zeros(35)
        grid_m_ = np.zeros(10)
        for i in range(35):
            grid_d[i] = round(self.d[i] / unit) * unit
        for i in range(2 * lstm_prediction.n_timestamp):
            grid_m_[i] = round(self.m_[i] / unit) * unit
            # print("grid_m_", grid_m_)
            # grid_m_[i] = 0
        if baselines == 'perfect_mobility' :
            grid_Lu_x = round(self.User_x / unit) * unit
            grid_Lu_y = round(self.User_y / unit) * unit
            grid_d = np.zeros(35)
            grid_m_ = np.zeros(10)
            for i in range(35):
                grid_d[i] = round(self.d[i] / unit) * unit
            for i in range(2 * lstm_prediction.n_timestamp):
                grid_m_[i] = round(self.m_[i] / unit) * unit
            # self.m_state = [self.User_x, self.User_y, self.b, self.d, self.m_]
            self.m_state = [grid_Lu_x, grid_Lu_y, self.b, grid_d, grid_m_]
        else:
            self.m_state = [grid_Lu_x, grid_Lu_y, self.b, grid_d, grid_m_]  # 进行网格划分

        Listd1 = self.m_state[3]  # 把上图的d对象提出出来，上图的结果记为Result
        Listd2 = self.m_state[4]  # 把上图的m_对象提出出来，上图的结果记为Result
        # print('Listd1', Listd1)
        # print('Listd2', Listd2)
        List_state = self.m_state[0:3]
        # print('List_state1', List_state)
        List_state.extend(Listd1)  # 数据顺序保持一样不变
        # print('List_state2', List_state)
        List_state.extend(Listd2)  # 数据顺序保持一样不变
        # print("self.t =", self.t)
        # print('List_state', List_state)
        Last_action = action
        if Count_file <= file_num - 1:
            if self.t >= (lstm_prediction.testing_days - lstm_prediction.n_timestamp - 1):
                self.t_use += (lstm_prediction.testing_days - lstm_prediction.n_timestamp - 1)
                Count_file += 1
                # print("Count_file", Count_file)
                # print("t_use", self.t_use)
                self.t = 0
                # print("迁移次数为  ", self.countmig)
                self.countmig = 0
            else:
                self.t = self.t + 1
        if Count_file == file_num:
            self.done = 1
            self.t_use = 0
            Count_file = 0
            # print("d[action] = ", self.d[action])
            # print("h[action] =", self.h[action])
            # print("C[action] = ", C[action])
            # print("Trans_average = ", Trans_average * 1000, "ms")
            # print("Tmig_average = ", Tmig_average * 1000, "ms")
            # Timeall_average = Trans_average + Tcomp_average + Tmig_average
            Timeall_average = 30 / Kaverage
            Time_ = np.log10(Timeall_average * 1000)
            # print("本次迭代平均总延时为  ", Timeall_average * 1000, "ms")
            # print("Kaverage  ", Kaverage)
            # self.reward = - (Timeall_average * 1000 - 20.3) * 1000
            # print("Kaverage_danci  ", Kaverage_danci)
            # Kuser_episode[episode] = Kaverage_danci
            # Kaverage = (Kaverage * episode + Kaverage_danci) / (episode + 1)

        return np.array(List_state, dtype=np.float32), self.reward, self.done

    def reset(self):
        self.m_state = [self.User_x, self.User_y, self.b, self.d, self.m_]
        Listd1 = self.m_state[3]  # 把上图的d对象提出出来，上图的结果记为Result
        Listd2 = self.m_state[4]  # 把上图的m_对象提出出来，上图的结果记为Result
        List_state = self.m_state[0:3]
        List_state.extend(Listd1)  # 数据顺序保持一样不变
        List_state.extend(Listd2)  # 数据顺序保持一样不变
        # print('state_reset',List_state)
        # print('self.state',self.state)
        self.counter = 0
        self.done = 0
        self.reward = 0
        return np.array(List_state, dtype=np.float32)

    # def render(self):
    #     # time.sleep(0.01)
    #     self.update()
